﻿/*
 * Copyright (c) 2025 粤港澳大湾区（广东）国创中心
 *
 * This file is a part of NctiCAEPre.
 *
 * NctiCAEPre is licensed under Mulan PSL v2.
 * You can use this software according to the terms and conditions of the Mulan PSL v2.
 * You may obtain a copy of Mulan PSL v2 at:
 *          http://license.coscl.org.cn/MulanPSL2
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 * See the Mulan PSL v2 for more details.
 *
 */

#include "UIOption.h"

#include <fstream>

#include <QObject>
#include <QCoreApplication>
#include <QStandardPaths>
#include <QDir>
#include <QDebug>

namespace NCTI {

const static QString syntaxVersion       = "v0.10";
const static QString uiOptionVersionDir  = QStringLiteral("uioption/%1").arg(syntaxVersion);
const static QString uiOptionDefaultPath = QStringLiteral("uioption/%1/uioption.json").arg(syntaxVersion);

const static QString uiOptionCustomDir  = QStringLiteral("uioption/%1/user").arg(syntaxVersion);
const static QString uiOptionCustomPath = QStringLiteral("%1/uioption.json").arg(uiOptionCustomDir);

UIOption::UIOption()
{
    QFileInfo fileInfo(getUIOptionPath(UIOptionType::System));
    if (!fileInfo.exists()) {
        // 生成默认配置文件
        initDefaultUIOption();
    }
}

UIOption::~UIOption()
{
}

bool UIOption::isVersionUpdated(const std::string& version)
{
    return QString::fromUtf8(version.c_str()) != syntaxVersion;
}

bool UIOption::LoadUIOption()
{
    mUIRibbon.tabs.clear();

    QString uiUserOptionPath = getUIOptionPath(UIOptionType::User);
    QFileInfo fileInfo(uiUserOptionPath);
    bool isFileExist = fileInfo.exists();
    if (isFileExist) { mUIRibbon = loadUIOption(uiUserOptionPath.toStdWString()); }

    if (!isFileExist || isVersionUpdated(mUIRibbon.version)) {
        // 使用默认配置文件
        if (!copyUIOptionFiles(getUIOptionPath(UIOptionType::System), uiUserOptionPath)) { return false; }
        // 再次加载
        mUIRibbon = loadUIOption(uiUserOptionPath.toStdWString());
    }

    std::sort(mUIRibbon.tabs.begin(), mUIRibbon.tabs.end(), [](const UITabDetail& a, const UITabDetail& b) {
        return a.index < b.index;
    });
    return !mUIRibbon.tabs.empty();
}

bool UIOption::copyUIOptionFiles(const QString& src, const QString& dst)
{
    QFileInfo fileInfo(src);
    if (!fileInfo.exists()) { return false; }

    QDir dstDir(QFileInfo(dst).dir());
    if (!dstDir.mkpath(".")) { return false; }

    QFile dstFile(dst);
    if (dstFile.exists() && !dstFile.remove()) {
        qWarning() << "Failed to remove existing file:" << dst;
        return false;
    }

    if (!QFile::copy(src, dst)) { return false; }

    UIRibbon uiRibbon = loadUIOption(src.toStdWString());
    for (const auto& tab : uiRibbon.tabs) {
        std::wstring srcFile = getJsonPath(UIOptionType::System, tab.object_name);
        std::wstring dstFile = getJsonPath(UIOptionType::User, tab.object_name, false);

        QString dstFilePath = QString::fromStdWString(dstFile);
        QFile tabDstFile(dstFilePath);
        if (tabDstFile.exists() && !tabDstFile.remove()) {
            qWarning() << "Failed to remove existing tab file:" << dstFilePath;
            return false;
        }

        if (!QFile::copy(QString::fromStdWString(srcFile), dstFilePath)) { return false; }
    }
    return true;
}

UIRibbon UIOption::loadUIOption(const std::wstring& jsonPath) const
{
    UIRibbon uiRibbon;
    try {
        std::ifstream file(jsonPath);
        if (file.is_open()) {
            json j   = json::parse(file);
            uiRibbon = j.get<UIRibbon>();
        }
    }
    catch (const json::parse_error& e) {
        qWarning() << "json parse error: " << e.what();
    }
    catch (const std::exception& e) {
        qWarning() << "std::exception: " << e.what();
    }
    return uiRibbon;
}

QString NCTI::UIOption::getUIOptionPath(UIOptionType type)
{
    // 获取%APPDATA%对应的目录（Roaming目录）
    QString appDataPath = QStandardPaths::writableLocation(QStandardPaths::AppDataLocation);

    QString dataDir = QDir(appDataPath).filePath("data");
    if (!QDir().mkpath(dataDir)) {
        qWarning() << "Cannot create data directory:" << dataDir;
        return QString{};
    }

    // 根据类型选择子路径
    const QString subPath = (type == UIOptionType::System) ? uiOptionDefaultPath : uiOptionCustomPath;

    if (type == UIOptionType::User) { qDebug() << "uioption path: " << QDir(dataDir).filePath(subPath); }
    return QDir(dataDir).filePath(subPath);
}

QString NCTI::UIOption::getUIDetailPath(UIOptionType type, const std::string& objectName)
{
    // 获取%APPDATA%对应的目录（Roaming目录）
    QString appDataPath = QStandardPaths::writableLocation(QStandardPaths::AppDataLocation);

    QString dataDir = QDir(appDataPath).filePath("data");

    QString uiDetailPath = (type == UIOptionType::System) ? uiOptionVersionDir : uiOptionCustomDir;

    uiDetailPath = QStringLiteral("%1/%2.json").arg(uiDetailPath).arg(QString::fromUtf8(objectName.c_str()));
    return QDir(dataDir).filePath(uiDetailPath);
}

void UIOption::initDefaultUIOption()
{
    // 生成默认配置json文件
    UIRibbon uiRibbon;
    uiRibbon.logo    = ":/App/app.png";
    uiRibbon.title   = "CAE前处理通用架构集成平台";
    uiRibbon.version = std::string(syntaxVersion.toUtf8());
    uiRibbon.tabs.push_back(UITabDetail{0, "文件", "file", true});
    uiRibbon.tabs.push_back(UITabDetail{1, "常规", "general", true});
    uiRibbon.tabs.push_back(UITabDetail{2, "草图", "sketch", true});
    uiRibbon.tabs.push_back(UITabDetail{3, "几何", "geometry", true});
    uiRibbon.tabs.push_back(UITabDetail{4, "仿真", "simulation", true});
    uiRibbon.tabs.push_back(UITabDetail{5, "我的", "custom", true});
    uiRibbon.tabs.push_back(UITabDetail{6, "AI", "ai", false});

    // 文件
    UIPage uiFilePage;
    uiFilePage.object_name = GetTabName(UI_FILE);
    {
        UIPanel uiAssembly{0, "assemblyPanel", "assemblyPanel"};
        UIPanel uiFile{1, "filePanel", "filePanel"};
        UIPanel uiImport{2, "importPanel", "importPanel"};
        UIPanel uiRedo{3, "redoPanel", "redoPanel"};
        UIPanel uiDelete{4, "deletePanel", "deletePanel"};
        UIPanel uiScriptPanel{5, "scriptPanel", "scriptPanel"};
        UIPanel uiObjectPanel{6, "objectPanel", "objectPanel"};

        addActionToPanel(uiAssembly,
                         UIAction(0, "创建装配", "new_assembly", ":/General/new_assembly.svg", "newAssembly"));
        addActionToPanel(uiAssembly, UIAction(1, "创建零件", "new_part", ":/General/new_part.svg", "newPart"));
        addActionToPanel(uiAssembly,
                         UIAction(2, "添加装配", "add_assembly", ":/General/add_assembly.svg", "addAssembly"));
        addActionToPanel(uiAssembly, UIAction(3, "添加零件", "add_part", ":/General/add_part.svg", "addPart"));
        addActionToPanel(uiAssembly,
                         UIAction(4, "导入零件", "import_part", ":/General/import_part.svg", "importAssemblyOrPart"));
        addActionToPanel(uiAssembly,
                         UIAction(5, "删除零件", "delete_part", ":/General/delete_part.svg", "removeAssemblyOrPart"));

        addActionToPanel(uiFile, UIAction(0, "打开", "open", ":/General/open.svg", "openNcti"));
        addActionToPanel(uiFile, UIAction(1, "保存", "save", ":/General/save.svg", "saveNcti"));
        addActionToPanel(uiFile, UIAction(2, "另存为", "saveas", ":/General/saveas.svg", "saveAsNcti"));
        addActionToPanel(uiFile, UIAction(3, "关闭文档", "close", ":/General/close.svg", "closeDocument"));

        addActionToPanel(uiImport, UIAction(0, "导入", "import", ":/General/import.svg", "importModel"));
        addActionToPanel(uiImport, UIAction(1, "导出", "export", ":/General/export.svg", "exportModel"));

        addActionToPanel(uiRedo, UIAction(0, "撤销", "undo", ":/General/undo.svg", "undo"));
        addActionToPanel(uiRedo, UIAction(1, "重做", "redo", ":/General/redo.svg", "redo"));

        addActionToPanel(uiDelete, UIAction(0, "删除", "delete", ":/General/delete.svg", "deleteObject"));

        UIAction scriptRun(0, "脚本运行", "script_run", ":/General/script_run.svg");
        scriptRun.vChild.push_back(UIAction(0, "执行脚本", "normal_run", ":/General/script_run.svg", "scriptRun"));
        scriptRun.vChild.push_back(
            UIAction(1, "执行装配体脚本", "assembly_run", ":/General/script_run.svg", "batchScriptRun"));
        scriptRun.vChild.push_back(
            UIAction(2, "执行多文档脚本", "multi_doc_run", ":/General/script_run.svg", "multicoreBatchScriptRun"));
        scriptRun.width = 70;
        addActionToPanel(uiScriptPanel, scriptRun);
        addActionToPanel(uiScriptPanel,
                         UIAction(1, "编辑器", "script_editor", ":/General/script_editor.svg", "scriptEdit"));
        addActionToPanel(uiScriptPanel, UIAction(2, "控制台", "console", ":/General/console.svg", "console"));

        addActionToPanel(uiObjectPanel, UIAction(0, "对象树", "object_tree", ":/General/object_tree.svg", "objectTree"));

        uiFilePage.panels.push_back(uiAssembly);
        uiFilePage.panels.push_back(uiFile);
        uiFilePage.panels.push_back(uiImport);
        uiFilePage.panels.push_back(uiRedo);
        uiFilePage.panels.push_back(uiDelete);
        uiFilePage.panels.push_back(uiScriptPanel);
        uiFilePage.panels.push_back(uiObjectPanel);
    }

    // 常规
    UIPage uiGeneral;
    uiGeneral.object_name = GetTabName(UI_GENERAL);
    {
        UIPanel uiShow{0, "showPanel", "showPanel"};
        UIPanel uiSixView{1, "sixViewPanel", "sixViewPanel"};
        UIPanel uiViewCtrl{2, "viewCtrlPanel", "viewCtrlPanel"};
        UIPanel uiViewMode{3, "viewModePanel", "viewModePanel"};
        UIPanel uiSelectMode{4, "selectModePanel", "selectModePanel"};
        UIPanel uiSetting{5, "settingPanel", "settingPanel"};

        addActionToPanel(uiShow, UIAction(0, "显示", "show_all_model", ":/General/show_all_model.svg", "showAll"));
        addActionToPanel(uiShow,
                         UIAction(1, "隐藏", "hide_select_model", ":/General/hide_select_model.svg", "hideSel"));
        addActionToPanel(uiShow,
                         UIAction(2, "独显", "show_select_model", ":/General/show_select_model.svg", "showSel"));

        UIGroup sixViewGroup{0};
        sixViewGroup.vChild.push_back(UIGroupItem{"", "xplus", ":/General/xplus.svg", "setView"});
        sixViewGroup.vChild.push_back(UIGroupItem{"", "xminus", ":/General/xminus.svg", "setView"});
        sixViewGroup.vChild.push_back(UIGroupItem{"", "yplus", ":/General/yplus.svg", "setView"});
        sixViewGroup.vChild.push_back(UIGroupItem{"", "yminus", ":/General/yminus.svg", "setView"});
        sixViewGroup.vChild.push_back(UIGroupItem{"", "zplus", ":/General/zplus.svg", "setView"});
        sixViewGroup.vChild.push_back(UIGroupItem{"", "zminus", ":/General/zminus.svg", "setView"});
        addActionToPanel(uiSixView, sixViewGroup);

        addActionToPanel(uiViewCtrl, UIAction(0, "西南视图", "isometric", ":/General/isometric.svg", "isometricView"));
        addActionToPanel(uiViewCtrl, UIAction(1, "聚焦", "location", ":/General/location.svg", "zoomAll"));
        addActionToPanel(uiViewCtrl, UIAction(2, "最大化", "zoom", ":/General/zoom.svg", "maxView"));
        addActionToPanel(uiViewCtrl, UIAction(3, "VTK视图", "vtk_view", ":/General/console.svg", "addVtkView"));
        addActionToPanel(uiViewCtrl,
                         UIAction(4, "Vulkan视图", "vulkan_view", ":/General/console.svg", "addVulkanView"));

        UIActionGroup viewModeActionGroup{0,
                                          2,
                                          2,
                                          "ribbon_group_visualMode",
                                          "显示模式",
                                          "title_visualMode",
                                          ":/General/display_mode.svg",
                                          "check_box"};
        viewModeActionGroup.vChild.push_back(UIActionGroupItem{1, 1, "体", "visual_body", "visualMode"});
        viewModeActionGroup.vChild.push_back(UIActionGroupItem{1, 2, "面", "visual_face", "visualMode"});
        viewModeActionGroup.vChild.push_back(UIActionGroupItem{2, 1, "线", "visual_edge", "visualMode"});
        viewModeActionGroup.vChild.push_back(UIActionGroupItem{2, 2, "点", "visual_vertex", "visualMode"});
        addActionToPanel(uiViewMode, viewModeActionGroup);

        UIActionGroup selectModeActionGroup{0,
                                            2,
                                            2,
                                            "ribbon_group_selectMode",
                                            "选择模式",
                                            "title_selectMode",
                                            ":/General/selection_mode.svg",
                                            "check_box"};
        selectModeActionGroup.vChild.push_back(UIActionGroupItem{1, 1, "体", "select_body", "selectMode"});
        selectModeActionGroup.vChild.push_back(UIActionGroupItem{1, 2, "面", "select_face", "selectMode"});
        selectModeActionGroup.vChild.push_back(UIActionGroupItem{2, 1, "线", "select_edge", "selectMode"});
        selectModeActionGroup.vChild.push_back(UIActionGroupItem{2, 2, "点", "select_vertex", "selectMode"});
        addActionToPanel(uiSelectMode, selectModeActionGroup);
        addActionToPanel(uiSelectMode, UIAction(1, "全选", "select_all", ":/General/select_all.svg", "selectAll"));

        addActionToPanel(uiSetting, UIAction(0, "选项卡", "option", ":/General/option.svg", "onOptions"));

        uiGeneral.panels.push_back(uiShow);
        uiGeneral.panels.push_back(uiSixView);
        uiGeneral.panels.push_back(uiViewCtrl);
        uiGeneral.panels.push_back(uiViewMode);
        uiGeneral.panels.push_back(uiSelectMode);
        uiGeneral.panels.push_back(uiSetting);
    }

    // 草图
    UIPage uiSketch;
    uiSketch.object_name = GetTabName(UI_SKETCH);
    {
        UIPanel uiDraftCommon{0, "draftCommonPanel", "draftCommonPanel"};
        UIPanel uiDraftGeo{1, "draftGeoPanel", "draftGeoPanel"};
        UIPanel uiDraftOperation{2, "draftOperationPanel", "draftOperationPanel"};
        UIPanel uiDraftView{3, "draftViewPanel", "draftViewPanel"};
        UIPanel uiDraftBodyOperation{4, "draftBodyOperationPanel", "draftBodyOperationPanel"};
        UIPanel uiDraftRebuild{5, "draftRebuildPanel", "draftRebuildPanel"};

        addActionToPanel(uiDraftCommon, UIAction(0, "新建草图", "draft_new", ":/Sketch/new.svg", "draftNew"));
        addActionToPanel(uiDraftCommon, UIAction(1, "进入草图", "draft_edit", ":/Sketch/edit.svg", "draftEdit"));
        addActionToPanel(uiDraftCommon, UIAction(2, "坐标系", "draft_coord", ":/Sketch/coord.svg", "draftCoord"));
        addActionToPanel(uiDraftCommon, UIAction(3, "删除草图", "draft_delete", ":/Sketch/coord.svg", "deleteDraft"));

        addActionToPanel(uiDraftGeo,
                         UIAction(0, "矩形", "draft_rectangle", ":/Sketch/rectangle.svg", "draftRectangle"));
        addActionToPanel(uiDraftGeo, UIAction(1, "圆", "draft_circle", ":/Sketch/circle.svg", "draftCircle"));
        addActionToPanel(uiDraftGeo, UIAction(2, "多边形", "draft_polygon", ":/Sketch/polygon.svg", "draftPolygon"));
        addActionToPanel(uiDraftGeo, UIAction(3, "椭圆", "draft_ellipse", ":/Sketch/ellipse.svg", "draftEllipse"));
        addActionToPanel(
            uiDraftGeo,
            UIAction(4, "连接两圆", "draft_circle_to_circle", ":/Sketch/circle_to_circle.svg", "draftCircleToCircle"));
        addActionToPanel(uiDraftGeo, UIAction(5, "直线", "draft_line", ":/Sketch/line.svg", "draftLine"));
        addActionToPanel(uiDraftGeo, UIAction(6, "圆弧", "draft_arc", ":/Sketch/arc.svg", "draftArc"));
        addActionToPanel(uiDraftGeo, UIAction(7, "多段线", "draft_wire", ":/Sketch/wire.svg", "draftWire"));
        addActionToPanel(uiDraftGeo, UIAction(8, "样条线", "draft_bspline", ":/Sketch/bspline.svg", "draftBspline"));
        addActionToPanel(uiDraftGeo,
                         UIAction(9, "中心线", "draft_centerline", ":/Sketch/centerline.svg", "draftCenterline"));
        addActionToPanel(uiDraftGeo, UIAction(10, "点", "draft_point", ":/Sketch/point.svg", "draftPoint"));

        addActionToPanel(uiDraftOperation,
                         UIAction(0, "到顶部", "move_to_top", ":/Sketch/move_to_top.svg", "draftMoveToTop"));
        addActionToPanel(uiDraftOperation,
                         UIAction(1, "到末端", "move_to_bottom", ":/Sketch/move_to_bottom.svg", "draftMoveToBottom"));
        addActionToPanel(uiDraftOperation, UIAction(2, "向上移", "upside", ":/Sketch/upside.svg", "draftUpside"));
        addActionToPanel(uiDraftOperation, UIAction(3, "向下移", "downside", ":/Sketch/downside.svg", "draftDownside"));
        addActionToPanel(uiDraftOperation, UIAction(4, "合并", "bunit", ":/Sketch/bunit.svg", "draftUnit"));
        addActionToPanel(uiDraftOperation, UIAction(5, "修剪", "bcut", ":/Sketch/bcut.svg", "draftCut"));
        addActionToPanel(uiDraftOperation, UIAction(6, "构面", "implode", ":/Sketch/implode.svg", "draftImplode"));
        addActionToPanel(uiDraftOperation, UIAction(7, "拆分", "explode", ":/Sketch/explode.svg", "draftExplode"));

        addActionToPanel(uiDraftView,
                         UIAction(0, "重置视图", "reset_view", ":/Sketch/reset_view.svg", "draftResetView"));
        addActionToPanel(uiDraftView, UIAction(1, "退出", "exit", ":/Sketch/exit.svg", "draftExit"));

        addActionToPanel(uiDraftBodyOperation,
                         UIAction(0, "拉伸特征", "extrude", ":/Sketch/extrude.svg", "draftExtrude"));
        addActionToPanel(uiDraftBodyOperation, UIAction(1, "旋转特征", "rotate", ":/Sketch/rotate.svg", "draftRotate"));
        addActionToPanel(uiDraftBodyOperation,
                         UIAction(2, "切换布尔", "boolMode", ":/Sketch/extrude.svg", "draftFeatureBoolean"));

        addActionToPanel(uiDraftRebuild, UIAction(0, "重建草图", "rebuild", ":/Sketch/rebuild.svg", "draftRebuild"));
        addActionToPanel(uiDraftRebuild,
                         UIAction(1, "生成模型", "modelization", ":/Sketch/modelization.svg", "draftModelization"));

        uiSketch.panels.push_back(uiDraftCommon);
        uiSketch.panels.push_back(uiDraftGeo);
        uiSketch.panels.push_back(uiDraftOperation);
        uiSketch.panels.push_back(uiDraftView);
        uiSketch.panels.push_back(uiDraftBodyOperation);
        uiSketch.panels.push_back(uiDraftRebuild);
    }

    // 几何
    UIPage uiGeometry;
    uiGeometry.object_name = GetTabName(UI_GEOMETRY);
    {
        UIPanel uiGeoModel{0, "geoModelPanel", "geoModelPanel"};
        UIPanel uiGeoFeature{1, "geoFeaturePanel", "geoFeaturePanel"};
        UIPanel uiGeoModelOp{2, "geoModelOpPanel", "geoModelOpPanel"};

        addActionToPanel(uiGeoModel, UIAction(0, "长方体", "box", ":/Geometry/box.svg", "executeBox"));
        addActionToPanel(uiGeoModel, UIAction(1, "圆柱体", "cylinder", ":/Geometry/cylinder.svg", "executeCylinder"));

        addActionToPanel(uiGeoFeature, UIAction(0, "布尔", "boolean", ":/Geometry/boolean.svg", "executeBoolean"));
        addActionToPanel(uiGeoFeature, UIAction(1, "圆角", "fillet", ":/Geometry/fillet.svg", "executeFillet"));
        addActionToPanel(uiGeoFeature, UIAction(2, "斜角", "chamfer", ":/Geometry/chamfer.svg", "executeChamfer"));
        addActionToPanel(uiGeoFeature, UIAction(3, "平移", "pan", ":/Geometry/pan.svg", "geoPan"));
        addActionToPanel(uiGeoFeature, UIAction(4, "缩放", "zoom", ":/Geometry/zoom.svg", "geoZoom"));
        addActionToPanel(uiGeoFeature, UIAction(5, "旋转", "rotate", ":/Geometry/rotate.svg", "geoRotate"));

        addActionToPanel(uiGeoModelOp,
                         UIAction(0, "移除特征", "remove_features", ":/Geometry/remove_features.svg", "removeFeature"));
        addActionToPanel(uiGeoModelOp,
                         UIAction(1, "移除面", "removing_faces", ":/Geometry/removing_faces.svg", "removeFace"));
        addActionToPanel(
            uiGeoModelOp,
            UIAction(2, "抽取要素", "extract_cell", ":/Geometry/extract_cell.svg", "executeExtractSubObj"));
        addActionToPanel(uiGeoModelOp,
                         UIAction(3, "填充内环", "fill_loop", ":/Geometry/fill_loop.svg", "executeFillLoop"));
        addActionToPanel(uiGeoModelOp,
                         UIAction(4, "组合", "create_compound", ":/Geometry/create_compound.svg", "executeCompound"));
        addActionToPanel(uiGeoModelOp,
                         UIAction(5, "分解", "explode_body", ":/Geometry/explode_body.svg", "executeExplodeBody"));
        addActionToPanel(uiGeoModelOp,
                         UIAction(6, "缝合", "sewing_bodies", ":/Geometry/sewing_bodies.svg", "executeSewing"));
        addActionToPanel(
            uiGeoModelOp,
            UIAction(7, "分离面", "separating_surface", ":/Geometry/separating_surface.svg", "executeSeparatFace"));
        addActionToPanel(uiGeoModelOp, UIAction(8, "拉伸", "extrude", ":/Geometry/extrude.svg", "createExtendFace"));
        addActionToPanel(uiGeoModelOp,
                         UIAction(9, "直线阵列", "linear_array", ":/Geometry/linear_array.svg", "linearArray"));
        addActionToPanel(uiGeoModelOp,
                         UIAction(10, "旋转阵列", "rotate_array", ":/Geometry/rotate_array.svg", "rotateArray"));
        addActionToPanel(uiGeoModelOp,
                         UIAction(11, "曲线阵列", "curve_array", ":/Geometry/curve_array.svg", "curveArray"));
        addActionToPanel(uiGeoModelOp,
                         UIAction(12, "曲线偏移", "curve_offset", ":/Geometry/curve_offset.svg", "curveOffset"));

        uiGeometry.panels.push_back(uiGeoModel);
        uiGeometry.panels.push_back(uiGeoFeature);
        uiGeometry.panels.push_back(uiGeoModelOp);
    }

    //仿真
    UIPage uiSimulation;
    uiSimulation.object_name = GetTabName(UI_SIMULATION);
    {
        UIPanel uiSimMesh{0, "simMeshPanel", "simMeshPanel"};
        UIPanel uiSimForce{1, "simForcePanel", "simForcePanel"};
        UIPanel uiSimSpc{2, "simSpcPanel", "simSpcPanel"};
        UIPanel uiSimMat{3, "simMatPanel", "simMatPanel"};
        UIPanel uiSimSelect{4, "simSelectPanel", "simSelectPanel"};
        UIPanel uiSimUtil{ 5, "simUtilPanel", "simUtilPanel" };

        addActionToPanel(
            uiSimMesh,
            UIAction(0, "面网格", "create_surface_mesh", ":/Simulation/create_surface_mesh.svg", "meshFromSurface"));
        addActionToPanel(
            uiSimMesh,
            UIAction(1, "体网格", "create_volume_mesh", ":/Simulation/create_volume_mesh.svg", "meshFromVolume"));
        addActionToPanel(
            uiSimMesh,
            UIAction(2, "网格质量", "show_mesh_quality", ":/Simulation/create_volume_mesh.svg", "meshShowMeshQuality"));

        addActionToPanel(uiSimForce,
                         UIAction(0, "集中力", "mesh_add_force", ":/Simulation/mesh_add_force.svg", "meshAddForce"));

        addActionToPanel(uiSimSpc,
                         UIAction(0, "单点约束", "mesh_add_spc", ":/Simulation/mesh_add_spc.svg", "meshAddSpc"));

        addActionToPanel(uiSimMat,
                         UIAction(0, "材料属性", "mesh_add_mat", ":/Simulation/mesh_add_mat.svg", "meshAddMat"));

        UIActionGroup gridSelectGroup{0,
                                      2,
                                      3,
                                      "ribbon_group_grid_selectMode",
                                      "网格拾取",
                                      "title_grid_selectMode",
                                      ":/General/selection_mode.svg",
                                      "radio_button"};
        gridSelectGroup.vChild.push_back(UIActionGroupItem{1, 1, "几何", "grid_geo", "meshGridSelect"});
        gridSelectGroup.vChild.push_back(UIActionGroupItem{1, 2, "节点", "grid_node", "meshGridSelect"});
        gridSelectGroup.vChild.push_back(UIActionGroupItem{1, 3, "单元", "grid_unit", "meshGridSelect"});
        gridSelectGroup.vChild.push_back(UIActionGroupItem{2, 1, "单元面", "grid_unit_face", "meshGridSelect"});
        gridSelectGroup.vChild.push_back(UIActionGroupItem{2, 2, "单元边", "grid_unit_edge", "meshGridSelect"});
        addActionToPanel(uiSimSelect, gridSelectGroup);


        addActionToPanel(uiSimUtil,
            UIAction(0, "快速选择", "mesh_quick_select", ":/Simulation/mesh_add_mat.svg", "meshQuickSelect"));

        addActionToPanel(uiSimUtil,
            UIAction(1, "切换引擎", "mesh_modify_mesh_type", ":/General/selection_mode.svg", "meshModifyMeshType"));

        uiSimulation.panels.push_back(uiSimMesh);
        uiSimulation.panels.push_back(uiSimForce);
        uiSimulation.panels.push_back(uiSimSpc);
        uiSimulation.panels.push_back(uiSimMat);
        uiSimulation.panels.push_back(uiSimSelect);
        uiSimulation.panels.push_back(uiSimUtil);
    }

    //AI
    UIPage uiAI;
    uiAI.object_name = GetTabName(UI_AI);
    {
        UIPanel uiidentifierPanel{0, "ai_identifier_panel"};
        addActionToPanel(uiidentifierPanel,
                         UIAction(0, "特征标识", "feature_identifier", ":/Sketch/new.svg", "featureIdentifier"));
        addActionToPanel(uiidentifierPanel,
                         UIAction(1, "特征列表", "feature_list", ":/Sketch/coord.svg", "featureList"));
        addActionToPanel(uiidentifierPanel,
                         UIAction(2, "圆角标识", "fillet_identifier", ":/Sketch/edit.svg", "filletIdentifier"));
        addActionToPanel(uiidentifierPanel,
                         UIAction(3, "孔标识", "hole_identifier", ":/Sketch/coord.svg", "holeIdentifier"));
        addActionToPanel(uiidentifierPanel,
                         UIAction(4, "Logo标识", "logo_identifier", ":/Sketch/coord.svg", "logoIdentifier"));

        UIPanel uiDraftGeo{1, "ai_extract_Panel"};
        addActionToPanel(uiDraftGeo,
                         UIAction(0, "提取圆角", "extract_fillet", ":/Sketch/rectangle.svg", "filletExtract"));
        addActionToPanel(uiDraftGeo, UIAction(1, "提取孔", "extract_hole", ":/Sketch/circle.svg", "holeExtract"));
        addActionToPanel(uiDraftGeo, UIAction(2, "提取Logo", "extract_logo", ":/Sketch/polygon.svg", "logoExtract"));

        UIPanel uiDraftOperation{2, "ai_reasoning_panel"};
        addActionToPanel(uiDraftOperation,
                         UIAction(0, "圆角推理", "fillet_reasoning", ":/Sketch/move_to_top.svg", "roundRecognition"));
        addActionToPanel(uiDraftOperation,
                         UIAction(1, "倒角推理", "chamfer_reasoning", ":/Sketch/move_to_bottom.svg", "chamferRecognition"));
        addActionToPanel(uiDraftOperation,
                         UIAction(2, "圆通孔推理", "through_hole_reasoning", ":/Sketch/move_to_bottom.svg", "throughHoleRecognition"));

        UIPanel uiDraftView{3, "ai_show_panel"};
        addActionToPanel(uiDraftView,
                         UIAction(0, "图结构", "show_graph_structure", ":/Sketch/reset_view.svg", "topoStructure"));
        addActionToPanel(uiDraftView,
                         UIAction(1, "边属性", "show_edge_properties", ":/Sketch/exit.svg", "edgeAttribute"));
        addActionToPanel(uiDraftView,
                         UIAction(2, "面属性", "show_face_properties", ":/Sketch/extrude.svg", "faceAttribute"));
        addActionToPanel(uiDraftView, UIAction(3, "UV网格", "show_uv_mesh", ":/Sketch/rotate.svg", "uvGrid"));
        addActionToPanel(uiDraftView, UIAction(4, "导出关联面", "fill_loop", ":/Sketch/extrude.svg", "exportLinkFace"));

        uiAI.panels.push_back(uiidentifierPanel);
        uiAI.panels.push_back(uiDraftGeo);
        uiAI.panels.push_back(uiDraftOperation);
        uiAI.panels.push_back(uiDraftView);
    }

    //我的
    UIPage uiCustom;
    uiCustom.object_name = GetTabName(UI_CUSTOM);
    {
        UIPanel uiCustomConfig{0, "custom_config_panel"};
        UIPanel uiCustomAdd{1, "custom_add_panel", "custom_add_panel"};

        addActionToPanel(uiCustomConfig,
                         UIAction(0, "命令设置", "custom_setting", ":/Custom/setting.svg", "openCustomSetting"));
        //addActionToPanel(uiCustomConfig, UIAction(1, "UI配置", "ui_option", ":/Custom/icon20.svg", "openUIOption"));

        uiCustom.panels.push_back(uiCustomConfig);
        uiCustom.panels.push_back(uiCustomAdd);
    }

    // 保存UI配置
    SaveUIOption(UIOptionType::System, uiRibbon);
    SaveUIPages(UIOptionType::System,
                std::vector<UIPage>{uiFilePage, uiGeneral, uiSketch, uiGeometry, uiSimulation, uiCustom, uiAI});
}

std::wstring UIOption::getJsonPath(UIOptionType type, const std::string& objectName, bool bCheckExists)
{
    QString uiDetailPath = getUIDetailPath(type, objectName);
    QFileInfo fileInfo(uiDetailPath);
    if (bCheckExists && !fileInfo.exists()) { return {}; }
    return uiDetailPath.toStdWString();
}

void UIOption::addActionToPanel(UIPanel& panel, const UIAction& action)
{
    panel.actions.push_back(action);
}

void UIOption::addActionToPanel(UIPanel& panel, const UIGroup& action)
{
    panel.groups.push_back(action);
}

void UIOption::addActionToPanel(UIPanel& panel, const UIActionGroup& action)
{
    panel.action_groups.push_back(action);
}

UIOption& UIOption::GetInst()
{
    static UIOption instance;
    return instance;
}

UIPage UIOption::LoadUIPage(UIOptionType type, const std::string& objectName)
{
    return loadUIPage(getJsonPath(type, objectName));
}

UIPage UIOption::loadUIPage(const std::wstring& jsonPath)
{
    if (jsonPath.empty()) { return UIPage(); }

    UIPage uiPage;
    try {
        std::ifstream file(jsonPath);
        if (file.is_open()) {
            json j = json::parse(file);
            uiPage = j.get<UIPage>();
        }
    }
    catch (const json::parse_error& e) {
        qWarning() << "json parse error: " << e.what();
    }
    catch (const std::exception& e) {
        qWarning() << "std::exception: " << e.what();
    }
    return uiPage;
}

QString UIOption::GetLogo()
{
    return QString::fromUtf8(mUIRibbon.logo.c_str());
}

QString UIOption::GetTitle()
{
    return QString::fromUtf8(mUIRibbon.title.c_str());
}

QString UIOption::GetVersion()
{
    return syntaxVersion;
}

std::vector<UITabDetail> UIOption::GetTabs(UIOptionType type)
{
    QString uiOptionPath = getUIOptionPath(type);
    QFileInfo fileInfo(uiOptionPath);
    if (!fileInfo.exists()) { return std::vector<UITabDetail>(); }

    UIRibbon uiRibbon = loadUIOption(uiOptionPath.toStdWString());
    return uiRibbon.tabs;
}

QStringList UIOption::GetUIOptionFiles()
{
    QStringList uiOptionFiles;
    QString uiOptionPath = QDir(QCoreApplication::applicationDirPath()).filePath(uiOptionCustomPath);
    uiOptionFiles << uiOptionPath;

    UIRibbon uiRibbon = loadUIOption(uiOptionPath.toStdWString());
    for (const auto& v : uiRibbon.tabs) {
        auto filePath = getJsonPath(UIOptionType::User, v.object_name);
        uiOptionFiles << QString::fromStdWString(filePath);
    }
    return uiOptionFiles;
}

UIRibbon UIOption::GetUIRibbon() const
{
    return mUIRibbon;
}

std::string UIOption::GetTabName(UIPageType type) const
{
    switch (type) {
        case NCTI::UI_FILE: return "file";
        case NCTI::UI_GENERAL: return "general";
        case NCTI::UI_SKETCH: return "sketch";
        case NCTI::UI_GEOMETRY: return "geometry";
        case NCTI::UI_AI: return "ai";
        case NCTI::UI_SIMULATION: return "simulation";
        case NCTI::UI_CUSTOM: return "custom";
        default: break;
    }
    return "unknown";
}

void UIOption::SaveUIOption(UIOptionType type, const UIRibbon& uiRibbon)
{
    QString uiOptionPath = getUIOptionPath(type);
    QFileInfo fileInfo(uiOptionPath);
    QDir dir = fileInfo.dir();
    if (!dir.exists()) {
        bool success = dir.mkpath(".");
        if (!success) {
            qWarning() << "Failed to create directory: " << dir.path();
            return;
        }
    }

    try {
        json j = uiRibbon;
        std::ofstream file(uiOptionPath.toStdWString());
        file << j.dump(4);
    }
    catch (const std::exception& e) {
        qWarning() << "Error: " << e.what();
    }
}

void UIOption::SaveUIPages(UIOptionType type, const std::vector<UIPage>& vPage)
{
    for (auto& page : vPage) {
        saveUIPage(type, page);
    }
}

void UIOption::saveUIPage(UIOptionType type, const UIPage& uiPage)
{
    std::wstring savePath = getJsonPath(type, uiPage.object_name, false);
    try {
        json j = uiPage;
        std::ofstream file(savePath);
        file << j.dump(4);
    }
    catch (const std::exception& e) {
        qWarning() << "Error: " << e.what();
    }
}

} // namespace NCTI